{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np \n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.cluster import MiniBatchKMeans\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>location</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3197468391</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3537982273</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>823183725</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>Stratford  Ontario</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1872223848</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>Tehran  Iran</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3429017717</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>627175141</td>\n",
       "      <td>ka_GE</td>\n",
       "      <td>1973</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-01T09:59:17.590Z</td>\n",
       "      <td>Tbilisi  Georgia</td>\n",
       "      <td>240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>2752000443</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1994</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-03T05:22:17.637Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>3473687777</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1965</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-10-03T12:19:29.975Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>2966052962</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1979</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-31T10:11:57.668Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>264876277</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1988</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-10-02T07:28:09.555Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user_id locale birthyear  gender                  joinedAt  \\\n",
       "0  3197468391  id_ID      1993    male  2012-10-02T06:40:55.524Z   \n",
       "1  3537982273  id_ID      1992    male  2012-09-29T18:03:12.111Z   \n",
       "2   823183725  en_US      1975    male  2012-10-06T03:14:07.149Z   \n",
       "3  1872223848  en_US      1991  female  2012-11-04T08:59:43.783Z   \n",
       "4  3429017717  id_ID      1995  female  2012-09-10T16:06:53.132Z   \n",
       "5   627175141  ka_GE      1973  female  2012-11-01T09:59:17.590Z   \n",
       "6  2752000443  id_ID      1994    male  2012-10-03T05:22:17.637Z   \n",
       "7  3473687777  id_ID      1965  female  2012-10-03T12:19:29.975Z   \n",
       "8  2966052962  id_ID      1979    male  2012-10-31T10:11:57.668Z   \n",
       "9   264876277  id_ID      1988  female  2012-10-02T07:28:09.555Z   \n",
       "\n",
       "             location  timezone  \n",
       "0    Medan  Indonesia     480.0  \n",
       "1    Medan  Indonesia     420.0  \n",
       "2  Stratford  Ontario    -240.0  \n",
       "3        Tehran  Iran     210.0  \n",
       "4                 NaN     420.0  \n",
       "5    Tbilisi  Georgia     240.0  \n",
       "6    Medan  Indonesia     420.0  \n",
       "7    Medan  Indonesia     420.0  \n",
       "8    Medan  Indonesia     420.0  \n",
       "9    Medan  Indonesia     420.0  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('users.csv')\n",
    "df.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38209"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(df.user_id.unique())  # 统计一共有多少个不同的用户"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Medan  Indonesia', 'Stratford  Ontario', 'Tehran  Iran', ...,\n",
       "       'New Brunswick  New Jersey', 'Monaco  California',\n",
       "       'Wakayama-shi  Wakayama  Japan'], dtype=object)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.location.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2805"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(df.location.unique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "user_id         0\n",
       "locale          0\n",
       "birthyear       0\n",
       "gender        109\n",
       "joinedAt       57\n",
       "location     5464\n",
       "timezone      436\n",
       "dtype: int64"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.isnull().sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据缺失值统计来看，location这个缺失值太多，就直接扔掉了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.drop(['user_id','location'],axis=1,inplace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "熟悉一下locale模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'locale' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-10-29c7a28a79f7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mlocale\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlocale_alias\u001b[0m  \u001b[1;31m#包含了数据中locale的所有取值\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'locale' is not defined"
     ]
    }
   ],
   "source": [
    "locale.locale_alias  #包含了数据中locale的所有取值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 特征编码,在这里不对空值进行填充，而是直接选取设置为一个新的类别\n",
    "import datetime\n",
    "import hashlib\n",
    "import locale\n",
    "\n",
    "from collections import defaultdict\n",
    "from sklearn.preprocessing import normalize\n",
    "\n",
    "class FeatureEng:\n",
    "    def __init__(self):\n",
    "         # 载入 locale，这是一个多语言模块\n",
    "        self.localeIdMap = defaultdict(int)\n",
    "        for i, l in enumerate(locale.locale_alias.keys()):\n",
    "          self.localeIdMap[l] = i + 1\n",
    "        \n",
    "        # 载入 gender id 字典\n",
    "        ##缺失补0\n",
    "        self.genderIdMap = defaultdict(int, {'NaN': 0, \"male\":1, \"female\":2})\n",
    "\n",
    "  \n",
    "    def getLocaleId(self, locstr):\n",
    "        return self.localeIdMap[locstr.lower()]\n",
    "\n",
    "    def getGenderId(self, genderStr):\n",
    "        return self.genderIdMap[genderStr]\n",
    "\n",
    "    def getJoinedYearMonth(self, dateString):\n",
    "        try:\n",
    "            dttm = datetime.datetime.strptime(dateString, \"%Y-%m-%dT%H:%M:%S.%fZ\")\n",
    "            #另外一种写法是：\n",
    "            # dttm = pd.to_datetime(df['joinedAt'][0],format='%Y-%m-%dT%H:%M:%S.%fZ')\n",
    "            #return \"\".join([str(dttm.year), str(dttm.month)])\n",
    "            return (dttm.year-2010)*12 + dttm.month\n",
    "        except:  #缺失补0\n",
    "          return 0\n",
    "\n",
    "    def getBirthYearInt(self, birthYear):\n",
    "        #缺失补0\n",
    "        try:\n",
    "          return 0 if birthYear == \"None\" else int(birthYear)\n",
    "        except:\n",
    "          return 0\n",
    "\n",
    "    def getTimezoneInt(self, timezone):\n",
    "        try:\n",
    "          return int(timezone)\n",
    "        except:  #缺失值处理\n",
    "          return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "FE = FeatureEng()\n",
    "\n",
    "cols = ['LocaleId', 'BirthYearInt', 'GenderId', 'JoinedYearMonth', 'TimezoneInt']\n",
    "n_cols = len(cols)\n",
    "userMatrix = np.zeros((df.shape[0],n_cols), dtype=np.int)\n",
    "\n",
    "for i in range(df.shape[0]): \n",
    "    userMatrix[i, 0] = FE.getLocaleId(df.loc[i,'locale'])\n",
    "    userMatrix[i, 1] = FE.getBirthYearInt(df.loc[i,'birthyear'])\n",
    "    userMatrix[i, 2] = FE.getGenderId(df.loc[i,'gender'])\n",
    "    userMatrix[i, 3] = FE.getJoinedYearMonth(df.loc[i,'joinedAt'])\n",
    "    userMatrix[i, 4] = FE.getTimezoneInt(df.loc[i,'timezone'])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>246</td>\n",
       "      <td>1993</td>\n",
       "      <td>1</td>\n",
       "      <td>34</td>\n",
       "      <td>480</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>246</td>\n",
       "      <td>1992</td>\n",
       "      <td>1</td>\n",
       "      <td>33</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>136</td>\n",
       "      <td>1975</td>\n",
       "      <td>1</td>\n",
       "      <td>34</td>\n",
       "      <td>-240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>136</td>\n",
       "      <td>1991</td>\n",
       "      <td>2</td>\n",
       "      <td>35</td>\n",
       "      <td>210</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>246</td>\n",
       "      <td>1995</td>\n",
       "      <td>2</td>\n",
       "      <td>33</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>280</td>\n",
       "      <td>1973</td>\n",
       "      <td>2</td>\n",
       "      <td>35</td>\n",
       "      <td>240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>246</td>\n",
       "      <td>1994</td>\n",
       "      <td>1</td>\n",
       "      <td>34</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>246</td>\n",
       "      <td>1965</td>\n",
       "      <td>2</td>\n",
       "      <td>34</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>246</td>\n",
       "      <td>1979</td>\n",
       "      <td>1</td>\n",
       "      <td>34</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>246</td>\n",
       "      <td>1988</td>\n",
       "      <td>2</td>\n",
       "      <td>34</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt\n",
       "0       246          1993         1               34          480\n",
       "1       246          1992         1               33          420\n",
       "2       136          1975         1               34         -240\n",
       "3       136          1991         2               35          210\n",
       "4       246          1995         2               33          420\n",
       "5       280          1973         2               35          240\n",
       "6       246          1994         1               34          420\n",
       "7       246          1965         2               34          420\n",
       "8       246          1979         1               34          420\n",
       "9       246          1988         2               34          420"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 先看看将我们得到的userMatrix转变成DataFrame的结果\n",
    "pd.DataFrame(data=userMatrix, columns=cols).head(10) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 聚类中的标准化或者说归一化\n",
    "因为我们要让让各个因子的权重变得一样，否则不同量纲的因子对结果的影响力是不同的，所以一般要标准化或者归一化处理，不然那些阈值大的feature完全会掩盖掉小的feature。\n",
    "举个例子：比如（0.1,10000）和（0.9,9999） 你说不归一化怎么算距离呀，直接算的话  那么第一个feature都是零头"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 再对它进行归一化处理\n",
    "userMatrix = normalize(userMatrix, norm=\"l1\", axis=0, copy=False)\n",
    "\n",
    "df_FE = pd.DataFrame(data=userMatrix, columns=cols)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000036</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>-0.000018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.000042</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt\n",
       "0  0.000036      0.000027  0.000019         0.000026     0.000036\n",
       "1  0.000036      0.000027  0.000019         0.000026     0.000031\n",
       "2  0.000020      0.000027  0.000019         0.000026    -0.000018\n",
       "3  0.000020      0.000027  0.000038         0.000027     0.000016\n",
       "4  0.000036      0.000027  0.000038         0.000026     0.000031\n",
       "5  0.000042      0.000027  0.000038         0.000027     0.000018\n",
       "6  0.000036      0.000027  0.000019         0.000026     0.000031\n",
       "7  0.000036      0.000027  0.000038         0.000026     0.000031\n",
       "8  0.000036      0.000027  0.000019         0.000026     0.000031\n",
       "9  0.000036      0.000027  0.000038         0.000026     0.000031"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_FE.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 一个参数点（聚类数据为K）的模型，在校验集上评价聚类算法性能\n",
    "import time\n",
    "from sklearn import metrics\n",
    "def mbk_cluster_analysis(K, train):\n",
    "    start = time.time()\n",
    "    \n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    \n",
    "    #K-means,在训练集上训练\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    mb_kmeans.fit(train)\n",
    "    \n",
    "    # 在训练集和测试集上测试\n",
    "    #y_train_pred = mb_kmeans.fit_predict(X_train)\n",
    "#     y_val_pred = mb_kmeans.predict(X_val)\n",
    "    \n",
    "    #以前两维特征打印训练数据的分类结果\n",
    "    #plt.scatter(X_train[:, 0], X_train[:, 1], c=y_pred)\n",
    "    #plt.show()\n",
    "\n",
    "    # K值的评估标准\n",
    "    #常见的方法有轮廓系数Silhouette Coefficient和Calinski-Harabasz Index\n",
    "    #这两个分数值越大则聚类效果越好\n",
    "    #CH_score = metrics.calinski_harabaz_score(X_train,mb_kmeans.predict(X_train))\n",
    "    CH_score = metrics.silhouette_score(train,mb_kmeans.predict(train))\n",
    "    \n",
    "    #也可以在校验集上评估K\n",
    "#     v_score = metrics.v_measure_score(y_val, y_val_pred)\n",
    "    \n",
    "    end = time.time()\n",
    "    print(\"CH_score: {}, time elaps:{}\".format(CH_score, int(end-start)))\n",
    "#     print(\"v_score: {}\".format(v_score))\n",
    "    \n",
    "    return CH_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 20\n",
      "CH_score: 0.6792468813689004, time elaps:59\n",
      "K-means begin with clusters: 40\n",
      "CH_score: 0.6978651152991572, time elaps:58\n",
      "K-means begin with clusters: 80\n",
      "CH_score: 0.6337440568278478, time elaps:50\n"
     ]
    }
   ],
   "source": [
    "# 设置超参数（聚类数目K）搜索范围\n",
    "Ks = [20,40,80]\n",
    "CH_scores = []\n",
    "for K in Ks:\n",
    "    ch = mbk_cluster_analysis(K, df_FE)\n",
    "    CH_scores.append(ch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看出最好的K应该是40"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1dbed5dfb00>]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1dbed30c908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后训练数据进行聚类。保存结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MiniBatchKMeans(batch_size=100, compute_labels=True, init='k-means++',\n",
       "        init_size=None, max_iter=100, max_no_improvement=10, n_clusters=40,\n",
       "        n_init=3, random_state=None, reassignment_ratio=0.01, tol=0.0,\n",
       "        verbose=0)"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n_clusters = 40\n",
    "km = MiniBatchKMeans(n_clusters = n_clusters)\n",
    "km.fit(df_FE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df_FE['cluster_100'] = km.predict(df_FE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "      <th>cluster_100</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000036</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>-0.000018</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000016</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.000042</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000018</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0.000036</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt  cluster_100\n",
       "0  0.000036      0.000027  0.000019         0.000026     0.000036            5\n",
       "1  0.000036      0.000027  0.000019         0.000026     0.000031           12\n",
       "2  0.000020      0.000027  0.000019         0.000026    -0.000018            1\n",
       "3  0.000020      0.000027  0.000038         0.000027     0.000016            8\n",
       "4  0.000036      0.000027  0.000038         0.000026     0.000031            4\n",
       "5  0.000042      0.000027  0.000038         0.000027     0.000018           16\n",
       "6  0.000036      0.000027  0.000019         0.000026     0.000031           12\n",
       "7  0.000036      0.000027  0.000038         0.000026     0.000031            4\n",
       "8  0.000036      0.000027  0.000019         0.000026     0.000031           12\n",
       "9  0.000036      0.000027  0.000038         0.000026     0.000031            4"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_FE.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df_FE.to_csv('users_FE.csv') # 保存结果"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
